/*
 * Source code written by Tácio S. Diogo.
 * Email: taciosd@gmail.com
 * Any copy or use without permission is prohibited.
 */
package app.comportamentos;

import app.agentes.Agente;
import app.agentes.JuizTse;
import app.agentes.Policial;
import app.reputacao.ACAO;
import app.modelo.Ambiente;
import app.modelo.Console;
import app.modelo.Denuncia;
import app.modelo.Propaganda;
import app.reputacao.CalculadoraDeReputacao;
import app.reputacao.ResultadoJulgamento;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.UnreadableException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Tácio S. Diogo
 */
public class JulgarProcessos extends CyclicBehaviour {
    private JuizTse juiz = null;
    
    public JulgarProcessos(JuizTse agent) {
        super(agent);
        
        juiz = (JuizTse) myAgent;
    }

    @Override
    public void action() {
        if (horaTerminarEleicoes()) {
            Ambiente.getInstance().executarAcao((Agente)myAgent, ACAO.TERMINAR_ELEICAO);
            myAgent.addBehaviour(new ContarVotos());
            myAgent.removeBehaviour(this);
            return;
        }
        
        ACLMessage msg = myAgent.receive();
        if (msg != null && msg.getConversationId().equals("Denuncia")) {
            try {
                Denuncia denuncia = (Denuncia) msg.getContentObject();
                ResultadoJulgamento resultado = processoJulgamento(denuncia);
                Console.escrever(myAgent, "Julguei o agente " + resultado.getNomeCulpado() + " como culpado!");
            } catch (UnreadableException ex) {
                Logger.getLogger(JulgarProcessos.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private boolean horaTerminarEleicoes() {
        Calendar dataFim = juiz.getDataFimSimulacao();
        Calendar dataAtual = Calendar.getInstance();
        return (dataAtual.after(dataFim));
    }
    
    public ResultadoJulgamento processoJulgamento(Denuncia denuncia) {
        ResultadoJulgamento resultadoJulgamento = julgar(denuncia.obterReu(), denuncia.obterAcusador(), denuncia.obterPropaganda());
  
        Double fator = CalculadoraDeReputacao.getNovaReputacao(resultadoJulgamento);
        juiz.atualizarReputacao(resultadoJulgamento.getNomeCulpado(), fator);
        return resultadoJulgamento;
    }
    
    private ResultadoJulgamento julgar(Agente agenteReu, Agente agenteAcusador, Propaganda propaganda){
        
        boolean assumiuCulpa = false;
        double percentagemCulpa;
        String nomeAgenteCulpado = agenteReu.getLocalName();
        
        if(ehDepoimentoPolicial(agenteAcusador)){
            percentagemCulpa = 1.0;
            Console.escrever("depoimento de policial");
        } else if(!verificarNormaAplicaReu(agenteReu)){
            nomeAgenteCulpado = agenteAcusador.getLocalName();
            percentagemCulpa = 1.0;
            Console.escrever("norma nao aplica a reu");
        }
        else if(adimiteCulpa(agenteReu)){
            percentagemCulpa = 1.0;
            assumiuCulpa = true;
            Console.escrever("adimite culpa");
        }else{ // aqui vamos aplicar consenso.
            
            percentagemCulpa = aplicarConsenso(agenteReu, agenteAcusador);
            if(percentagemCulpa < 0.5)
                nomeAgenteCulpado = agenteAcusador.getLocalName();
            
            Console.escrever("aplicando consenso");
        }
        
        Console.escrever("-------CULPADO------- " + nomeAgenteCulpado);
        double poderNorma = juiz.obterPoderNorma(propaganda.getTipo());
        return new ResultadoJulgamento(nomeAgenteCulpado, percentagemCulpa, poderNorma, assumiuCulpa);
    }
    
    private double aplicarConsenso(Agente agenteReu, Agente agenteAcusador){
        return aplicarVeredicto(agenteReu, agenteAcusador);
    }
    
    private boolean verificarNormaAplicaReu(Agente agenteReu){
        return juiz.verificarNormaAplicaReu(agenteReu);
    }
    
    //TODO adicionar Comportamento
    private boolean adimiteCulpa(Agente agenteReu){
        return agenteReu.getEtica() > JuizTse.ETICA_ASSUMIR_CULPA;
    }
    
    private boolean ehDepoimentoPolicial(Agente agenteAcusador){
        return agenteAcusador instanceof Policial;
    }

    public double aplicarVeredicto(Agente reu, Agente acusador){
        Double valorReputacao = juiz.obterReputacao(acusador.getLocalName());
        
        List<Agente> lista = montarJuri();
        for(Agente agente : lista){
            valorReputacao += juiz.obterReputacao(agente.getLocalName());
        }
        
        return valorReputacao / (lista.size() + 1);
    }
    
    //TODO randomizar 3 agentes
    private List<Agente> montarJuri(){
        List<Agente> listaAgente = new ArrayList<Agente>();
        return listaAgente;
    }
}
